﻿#pragma once

#include <cstdint>
#include <chrono>
#include <functional>

#define INVALID_TIMERID 0

namespace LH
{
class ITimer
{
public:
    using TimerID = uint64_t;
    using TimerListener = std::function<void(TimerID)>;
public:
    ITimer() = default;
    virtual ~ITimer() = default;

    /**
     * @brief 创建一个定时任务。延时执行回调函数
     *
     * @param listener 回调函数
     * @param msecs    延时时间
     * @return 返回定时器唯一id
     */
    virtual TimerID schedule(
        TimerListener listener,
        std::chrono::milliseconds msecs) = 0;

    
    /**
      * @brief 创建一个定时任务。按照固定频率执行回调函数 
      * 
      *  第一次运行 firstRunTime=now+msecs，第n次 firstRunTime +  msecs * n
      *
      * @param listener 回调函数
      * @param msecs    时间间隔
      * @param delay    第一次执行延时时间。默认0，立即执行
      * @return 返回定时器唯一id
      */
    virtual TimerID scheduleAtFixedRate(
        TimerListener listener,
        std::chrono::milliseconds msecs,
        std::chrono::milliseconds delay = std::chrono::milliseconds{ 0 }) = 0;

    /**
      * @brief 创建并执行一个回调，该回调在给定的初始延迟后首先启用，随后在给定的时间段内启用
      *
      * 这个计时器将重复并首先在初始延迟时触发，
      * 然后是“now”+msecs，然后是“now”+msecs。
      * 
      * @param listener 回调函数
      * @param msecs    执行计时器的周期
      * @param delay    第一次执行延时时间。默认0，立即执行
      * @return 返回定时器唯一id
      */
    virtual TimerID scheduleAtFixedDelay(
        TimerListener listener,
        std::chrono::milliseconds msecs,
        std::chrono::milliseconds delay = std::chrono::milliseconds{ 0 }) = 0;


    /**
     * @brief  重新安排一个存在的定时任务
     *
     * @param id   定时器id
     * @param msecs 时间间隔
     * @param repeat 是否重复
     * @return 
     */
    virtual bool reschedule(TimerID id,
        std::chrono::milliseconds msecs,
        bool repeat = false) = 0;

    /**
     * @brief 根据id取消定时任务
     * @param id
     */
    virtual void cancel(TimerID id) = 0;

    /**
     * @brie 取消所有定时任务 
     */
    virtual void cancelAll() = 0;

public:
    inline TimerID schedule(TimerListener listener, int msecs) {
        return schedule(listener, std::chrono::milliseconds{ msecs });
    }
    
    inline TimerID scheduleAtFixedRate(TimerListener listener, int msecs, int delay = 0) {
        return scheduleAtFixedRate(listener, std::chrono::milliseconds{ msecs }, std::chrono::milliseconds{ delay });
    }
    
    inline TimerID scheduleAtFixedDelay(TimerListener listener, int msecs, int delay = 0) {
        return scheduleAtFixedDelay(listener, std::chrono::milliseconds{ msecs }, std::chrono::milliseconds{ delay });
    }

    inline bool reschedule(TimerID id, int msecs, bool repeat = false) {
        return reschedule(id, std::chrono::milliseconds{ msecs }, repeat);
    }
     
};
}// namespace LH
